﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using SuiHan.Commons.Daemon;
using SuiHan.Commons.Daemon.Util;
using SuiHan.Commons.Logging;

namespace SuiHan.ProcessDaemon {
    delegate bool ConsoleEventDelegate(int eventType);

    public class DaemonApplication {
        private static readonly Logger logger = LoggerFactory.GetCurrentLogger();
        private static readonly string ShutdownProcessPath = ContextUtils.GetContextResourcePath("daemon-shutdown.exe");

        private static List<DaemonProcess> daemons = new();

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool SetConsoleCtrlHandler(ConsoleEventDelegate callback, bool add);

        public static void Start() {
            SetConsoleCtrlHandler(OnApplicationExit, true);
            AppDomain.CurrentDomain.ProcessExit += OnProcessExit;

            daemons = DaemonUtils.LoadDaemons();
            if (daemons.Count == 0) {
                logger.Warn("没有设置任何守护进程");
            } else {
                daemons.ForEach(it => it.Start());
            }
        }

        private static void OnProcessExit(object sender, EventArgs eventArgs) {
            KillKillableProcess();
        }

        private static bool OnApplicationExit(int eventType) {
            KillKillableProcess();
            return false;
        }

        private static void KillKillableProcess() {
            StartShutdownProcess();
        }

        public static void Shutdown() {
            daemons.ForEach(it => {
                if (it.Killable) {
                    it.KillProcess();
                }
            });
        }

        private static void StartShutdownProcess() {
            try {
                using Process process = Process.Start(new ProcessStartInfo(ShutdownProcessPath) {
                    CreateNoWindow = true,
                    UseShellExecute = false,
                    WindowStyle = ProcessWindowStyle.Hidden,
                    RedirectStandardOutput = true,
                });
            } catch (Exception e) {
                logger.Error(e);
            }
        }
    }
}
